package com.hrms.view;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.hrms.core.Constants;
import com.hrms.core.Constants.Transaction;
import com.hrms.core.Utils;
import com.hrms.domain.BlockingStep;
import com.hrms.domain.BusinessObjectImpl;
import com.hrms.domain.DailyCell;
import com.hrms.domain.Task;
import com.hrms.model.TaskListModel;

public class TaskView extends TeamDashboardView{
	
	public static final String SELECTED_DATE = Task.TYPE+"_SelectedDate";
	public static final String CELL_DATE = Task.TYPE+"_"+DailyCell.TYPE+"_cellDate";
	public static final String TASK_KEY = Task.TYPE+"_"+DailyCell.TYPE+"_taskKey";
	
	private Date fromDate = null;
	private Date toDate = null;
	private Date selectedDate = null;
	private Date cellDate = null;
	private Key taskKey = null;
	private String status = null;
	
	private Boolean isPlannedTaskView = false;
	
	public TaskView() {
		super();
	}
	
	public void service(HttpServletRequest req, HttpServletResponse res) {
		super.service(req, res);
	}

	@Override
	protected void persistEvents() {
		log.info(getUserAction());
		if (StringUtils.isNotBlank(getUserAction())) {

			try {

				if (Constants.Action.NEW.toString().equals(getUserAction())) {
						Task task = new Task(getParameterMap());
						String status = Constants.Status.InProgress.toString();
						if(isPlannedTaskView){
							status = Constants.Status.Planned.toString();
						}
						task.setStatus(status);
						setWarnings( task.fireEvents(getUserAction(), getReq()) );
						
				}else if (Constants.Action.EDIT.toString().equals(getUserAction())) {
					
					if((isSuper() || isTeam()) && (cellDate != null) && (taskKey!=null)){
						
						DailyCell dc = null;
						
						dc = BusinessObjectImpl.selectAsSingleResult(DailyCell.class, 
									"where userId == :p1 && date == :p2 && taskKey == :p3",
									new Object[]{ getUserId(), cellDate, taskKey} );
						
						if(dc!=null){
							dc.setCelldata(getMapValue("celldata"));
						}else{
							addAsAParameter("date", getMapValue(CELL_DATE));
							addAsAParameter("taskKey", getMapValue(TASK_KEY));
							dc = new DailyCell(getParameterMap());
						}

						setWarnings( dc.fireEvents(getUserAction(), getReq()) );
						
					}else{
						setWarnings("Access Denied");
						return;
					}
					
				}else if (Constants.Action.TASKCHANGE.toString().equals(getUserAction())) {
					if(isSuper() || isTeam()) {
					if(StringUtils.isNotBlank(status)){
						Boolean taskSuccess = Boolean.TRUE; 
						Task task = BusinessObjectImpl.selectById(Task.class, taskKey);
					
						if(task != null){
							
							BlockingStep bs = null;
							String userAction = Constants.Action.NEW.toString();
							
								if(status.equals(Constants.Status.Blocking.toString())){
									bs = new BlockingStep(getParameterMap());
									bs.setTaskKey(taskKey);
								}else if(task.getStatus().equals(Constants.Status.Blocking.toString())){
									userAction = Constants.Action.EDIT.toString();
									bs = BusinessObjectImpl.selectAsSingleResult(BlockingStep.class, "where taskKey == :tk && status == :stat" , new Object[]{ taskKey , BlockingStep.STATUS.Blocking.toString()});
									if(bs != null){
										bs.setStatus(BlockingStep.STATUS.Close.toString());
									}
								}

								if(bs != null){
									if(bs.fireEvents(userAction, getReq()).equals(Constants.UNKNOWN_REQUEST)){
										taskSuccess = Boolean.FALSE;
									}
								}
								
								if(taskSuccess){
									task.setStatus(status);
									setWarnings( task.fireEvents(Constants.Action.EDIT.toString(), getReq()) );
								}
						}
					
					}
					}else{
						setWarnings("Access Denied");
						return;
					}
				}else if (Constants.Action.BATCH_EDIT.toString().equals(getUserAction())) {
					if(isSuper() || isTeam()) {
						
					Integer no = 0;
					no++;
					String namer = Task.TYPE +"_"+no;
					List<DailyCell> dclist = new ArrayList<DailyCell>();
					DailyCell dc = null;
					
					log(namer);
					while( getMapValue(namer+"_key") != null ){ 
						log(namer);
						//_celldata_date

						for(Integer count=0; count < 8 ; count++){
							
							String dcData = getMapValue(namer+ "_"+ DailyCell.TYPE +"_"+count+"_celldata");
							String dcDate = getMapValue(namer+ "_"+ DailyCell.TYPE +"_"+count+"_celldata_date");
							log(dcData);
							log(dcDate);
							if(StringUtils.isNotBlank(dcData) && StringUtils.isNotBlank(dcDate)){
								
								dc = new DailyCell();
								dc.setTaskKey(KeyFactory.stringToKey(getMapValue(namer+"_key")));
								dc.setCelldata(dcData);
								dc.setDate(Utils.parseDate(dcDate));
								dc.setUserId(getUserId());
								dclist.add(dc);
							}
						}
						
						//namer += "_"+ DailyCell.TYPE +"_"+count;
						no++;						
						namer =  Task.TYPE +"_"+no;
					}
					
					executeDailyCellBatchEdit(dclist);
				}
				}else{
					setWarnings("Access Denied");
					return;
				}

			} catch (Exception e) {
				setWarnings( Transaction.Failed.getMsg() ); 
				log.log(Level.SEVERE, getWarnings(), e);
			}
		}
	}
	
	private static void executeDailyCellBatchEdit(List<DailyCell> dclist) {
		for (DailyCell dc : dclist) {
			DailyCell dctmp = null;
			dctmp = BusinessObjectImpl.selectAsSingleResult(DailyCell.class, 
						"where userId == :p1 && date == :p2 && taskKey == :p3",
						new Object[]{ dc.getUserId(), dc.getDate(), dc.getTaskKey() } );
			
			if(dctmp!=null){
				dctmp.setCelldata(dc.getCelldata());
				dctmp.save();
			}else{
				dc.save();
			}
		}
	}

	public List<Task> getTaskList() {
		List<Task> taskList = BusinessObjectImpl.select(Task.class, 
				"where userId == :user  ",
				new Object[]{ getUserId() } 
		);
		
		return taskList;
	}
	
	public Collection<TaskListModel> getTaskViewModel(){

		/*List<DailyCell> dcList = BusinessObjectImpl.select(DailyCell.class,
				"where date >= :p0 && date <= :p1 && task == t && t.userId== :p2 order by date asc ",
				new Object[]{ fromDate, toDate, userId },
				new String[]{ Task.TYPE + " t"}
				);
				*/
		
		List<DailyCell> dcList = BusinessObjectImpl.select(DailyCell.class,
				"where date >= :p0 && date <= :p1 && userId== :p2 order by date asc ",
				new Object[]{ fromDate, toDate, getUserId() }
				);
		
			log(dcList.size());
		
		List<Task> pendingTasks = BusinessObjectImpl.select(Task.class, "where status != :p && userId== :p1", new Object[]{ Constants.Status.Completed.toString(), getUserId() } );
			
		 Map<Key, TaskListModel> model = new HashMap<Key, TaskListModel>();
		
		for (DailyCell dc : dcList) {
			
			TaskListModel tmp = null;
			Key parentKey = dc.getTaskKey();
			Task task = null;
			
			if(model.containsKey(parentKey)){
				tmp = model.get(parentKey);
			}else{
				
				for(Task ptk : pendingTasks){
					if( ptk.getKey().equals(parentKey) ){
						task = ptk;
						break;
					}
				}
				
				if(task == null){
					task = BusinessObjectImpl.selectById(Task.class, parentKey);	
				}
				
				tmp = new TaskListModel();
				tmp.setTask(task);
			}
			tmp.addDailyCells(dc);
			model.put(parentKey, tmp);
			log(model.size());
		}
				
		for(Task tsk : pendingTasks){
			if(!model.keySet().contains(tsk.getKey())){
				TaskListModel tmp = new TaskListModel();
				tmp.setTask(tsk);
				model.put(tsk.getKey(), tmp);
			}
		}
		
		return model.values();
	}
	
	public List<Date> getDateRange(){
		List<Date> dateList = new ArrayList<Date>();
		Calendar cal = Calendar.getInstance();
		cal.setTime(fromDate);
		
		while(!cal.getTime().after(toDate)){
			dateList.add(cal.getTime());
			cal.add(Calendar.DATE, 1);
		}
		
		return dateList;
	}
	

	@Override
	protected void initalize() {
		super.initalize();
		log(getMapValue(SELECTED_DATE));
		selectedDate = Utils.safeParseDate(getMapValue(SELECTED_DATE), Utils.getTodayDate());
		toDate = DateUtils.addDays(selectedDate, 3);
		fromDate = DateUtils.addDays(selectedDate, -3);
	
		log(toDate);
		log(fromDate);
		
		if(StringUtils.isNotEmpty(getMapValue(CELL_DATE))){
			cellDate = Utils.safeParseDate(getMapValue(CELL_DATE));
		}
		
		if(StringUtils.isNotEmpty(getMapValue(TASK_KEY))){
			taskKey = KeyFactory.stringToKey(getMapValue(TASK_KEY));
		}
		
		status = StringUtils.defaultIfEmpty(getMapValue("status"), null);
		
		isPlannedTaskView = getReq().getRequestURI().startsWith(Constants.PLANNED_ITEMS.getPage());
		
	}

	public Date getSelectedDate() {
		return selectedDate;
	}
	
	public Date getNavigatableDate(){
		return selectedDate != null ? selectedDate : DateUtils.addDays(toDate, -3);
	}

	public Boolean isPlannedTaskView() {
		return isPlannedTaskView;
	}
	
	public Boolean showDailyCell(){
		return Boolean.TRUE;
	}
	
	public Boolean isViewable(){
		return (isSuper() || isTeam());
	}
	
}
